//
// Created by yunlang on 2021/12/8.
//

#ifndef FILEARCHIVER_HUFFMANCOMPRESSION_H
#define FILEARCHIVER_HUFFMANCOMPRESSION_H
#include "PriorityQueue.h"
#include<vector>
#include <unordered_map>
#include "hfmCodeBitSet.h"
#include "TreeNode.h"
using namespace std;
class HuffmanCompression
{
private:
    TreeNode * treeRoot;
//    struct nodePtrCmp { bool operator() (TreeNode* a, TreeNode* b) { return (a->weight) > (b->weight); } };
//    priority_queue< TreeNode*, vector<TreeNode*>, nodePtrCmp > nodeQueue;
    PriorityQueue nodeQueue;
    void calcWeight(const unsigned char* dataPtr, unsigned int dataSize,
                    unordered_map<unsigned char, unsigned int >& weightMap);
    void generateEncodedNodeQueue(const unordered_map<unsigned char,unsigned int> &weightMap);
    void generateDecodeNodeQueue(const vector<pair<unsigned char,unsigned int>>&weightMapArr);
    void generateTree();
    void dfs(TreeNode* node, hfmCodeBitSet& path,unordered_map<unsigned char, hfmCodeBitSet> & resCodeMap);
    void generateCodeMap(unordered_map<unsigned char, hfmCodeBitSet>& resCodeMap);
    void generateEncode(const unsigned char *rawDataPtr, unsigned int rawDataSize, const unordered_map<unsigned char, hfmCodeBitSet> &resCodeMap, unsigned char* &outputDataPtr, unsigned int outputDataBitSize);
    unsigned int calcEncodedOutputSize(const unordered_map<unsigned char, unsigned int > &weightMap,const unordered_map<unsigned char, hfmCodeBitSet> &resCodeMap);
    unsigned int calcDecodeOutputSize(const vector<pair<unsigned char,unsigned int>>&weightMap);
    void generateDecodedOutput(const unsigned char* rawDataPtr,unsigned int rawDataBitSize,
                               unsigned char * &outputDataPtr,unsigned int outputDAtaSize);
public:
    void getEncodedData(const unsigned char *rawDataPtr,
                        unsigned int rawDataSize,
                        unordered_map<unsigned char, unsigned int > &dstWeightMap,
                        unsigned char * &outputDataPtr, unsigned int &outputDataBitSize);
    void getDecodeData(const unsigned char *rawDataPtr,unsigned int rawDataBitSize,
                       const vector<pair<unsigned char,unsigned int>> &srcWeightMapArr,
                       unsigned char* &outputDataPtr,unsigned int &outputDataSize);

};

#endif //FILEARCHIVER_HUFFMANCOMPRESSION_H